package com.echo.echovividlive.websocket;

import com.alibaba.fastjson.JSONObject;
import com.echo.echovividlive.domain.vo.BulletScreenOrGift;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.echo.echovividlive.common.Constants.LIVE_GIFT_KEY;
import static com.echo.echovividlive.common.Constants.LIVE_USER_COUNTER;

@Slf4j
@Component
public class LivingRoom implements WebSocketHandler {

    // 记录用户与直播间直接的关系
    private static final Map<Integer,Integer> userMap = new ConcurrentHashMap<>();
    // 记录直播间里面的所有用户
    private static final Map<Integer,List<WebSocketSession>> liveRoomMap = new ConcurrentHashMap<>();

    @Resource
    private StringRedisTemplate stringRedisTemplate;

//    @OnOpen
//    public void onOpen(Session session){
//
//        System.out.println("连接已建立..."+session.getId());
//    }
//
//    @OnMessage
//    public void onMessage(Session session,String message) throws IOException {
//        System.out.println("来自"+session.getId()+"的消息"+message);
//        session.getBasicRemote().sendText("发送: " + message);
//
//    }
//
//    @OnClose
//    public void onClose(Session session){
//        System.out.println(session.getId()+ "断开连接...");
//    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Integer userId = (Integer) session.getAttributes().get("userId");
        // 获取直播间id
        String pathParam = session.getUri().getPath();
        Integer path = Integer.parseInt(pathParam.substring(pathParam.lastIndexOf('/')+1));
        userMap.put(userId,path);
        List<WebSocketSession> orDefault = liveRoomMap.getOrDefault(path, new ArrayList<>());
        orDefault.add(session);
        liveRoomMap.put(path,orDefault);
        // 统计在线观看人数
        Integer count = liveRoomMap.getOrDefault(path,new ArrayList<>()).size();
        liveRoomMap.get(path).forEach(webSocketSession -> {
            try {
                webSocketSession.sendMessage(new TextMessage(count.toString()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
        stringRedisTemplate.opsForValue().set(LIVE_USER_COUNTER+path,count.toString());
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        String payload = message.getPayload().toString();
        if (JSONObject.isValid(payload)) {
            BulletScreenOrGift bulletScreen = JSONObject.parseObject(payload, BulletScreenOrGift.class);
            // 获取当前用户所在直播间
            Integer roomId = userMap.get(bulletScreen.getUserId());
            List<WebSocketSession> webSocketSessions = liveRoomMap.get(roomId);
            // 同步给每一个用户
            webSocketSessions.forEach(webSocketSession -> {
                try {
                    webSocketSession.sendMessage(new TextMessage(payload));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            // 礼物信息记录
            if(bulletScreen.getIsGift()){
                Integer giftTotalValue = bulletScreen.getGiftCount() * bulletScreen.getGiftValue();
                stringRedisTemplate.opsForList().leftPush(LIVE_GIFT_KEY+roomId,
                        giftTotalValue.toString());
            }
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        Integer userId = (Integer) session.getAttributes().get("userId");
        Integer roomId = userMap.get(userId);
        userMap.remove(userId);
        List<WebSocketSession> orDefault = liveRoomMap.getOrDefault(roomId, new ArrayList<>());
        orDefault.remove(session);
        liveRoomMap.put(roomId,orDefault);
        // 统计在线观看人数
        Integer count = liveRoomMap.getOrDefault(roomId,new ArrayList<>()).size();
        liveRoomMap.get(roomId).forEach(webSocketSession -> {
            try {
                webSocketSession.sendMessage(new TextMessage(count.toString()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
        stringRedisTemplate.opsForValue().set(LIVE_USER_COUNTER+roomId,count.toString());
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}
